from datetime import datetime
from typing import Dict, Optional

from common.basic_mongo import get_mongo_collection
from device_status_mgm.device_status_constant import (DB_DEVICE_EXCEPTION_STATUS_INTERVAL_DOCUMENT,
                                                      DB_RAPID_RESPONSE_DOCUMENT,
                                                      RAPID_RESPONSE_REASON_CONFIG_DB,
                                                      RAPID_RESPONSE_REASON_COUNT_DB)
from common.utils import now_time_string, string_to_datetime
from mg_app_framework import get_context
from pymongo import ReturnDocument


async def filter_mark_rapid_reason(reason_code: str) -> Optional[Dict]:
    reason_code = str(reason_code)
    rapid_response_config_handler = get_mongo_collection(
        collection_name=RAPID_RESPONSE_REASON_CONFIG_DB
    )
    reason_of_breaks_raw = (
            await rapid_response_config_handler.find_one(
                {
                    "key": "reason_of_breaks",
                }
            )
            or {}
    )
    reason_of_breaks = reason_of_breaks_raw.get("value", {})
    reason_raw_detail = (
            await rapid_response_config_handler.find_one(
                {
                    "key": "reason_raw",
                }
            )
            or {}
    )

    reason_raw = reason_raw_detail.get("value", [])
    reason_mapper = {
        str(item["原因编码"]): {
            "reason_class": item["分类名称"],
            "reason_detail": item["原因名称"],
            "is_excluded": item["原因名称"] != "停机损失",
            "status": reason_of_breaks.get(item["原因名称"], None),
        }
        for item in reason_raw
    }

    res = reason_mapper.get(reason_code) or None
    return res


async def build_mark_rapid_reason(reason_code: str, user_code: str) -> Dict:
    user_map = get_context("user_map") or {}
    mark_reason = await filter_mark_rapid_reason(reason_code)
    if mark_reason:
        return {
            "up_pc_report": True,
            "reason_class": mark_reason["reason_class"],
            "reason_detail": mark_reason["reason_detail"],
            "excluded": mark_reason["is_excluded"],
            "report_time": now_time_string(),
            "report_user": user_code,
            "report_user_code": user_map.get(user_code, ""),
            "response_identifier": [],
            "response_identifier_close": [],
        }
    return {}


async def single_mark_break_interval(
        *,
        device_code: str,
        start_time: str,
        update_mark_reason: Dict = None,
):
    """
    将目标快反数据进行标记, 一定会标记状态时间片, 如果记录为快反则也会标记快反记录
    :param device_code:
    :param start_time:
    :param update_mark_reason:
    :return:
    """
    start_time = datetime.strptime(start_time, "%Y-%m-%d %H:%M:%S")
    reason_class = update_mark_reason.get("type", "空中断原因分类")
    reason_detail = update_mark_reason.get("detail", "空中断原因明细")
    update_mark_reason["report_time"] = string_to_datetime(update_mark_reason["report_time"])
    device_interval_handler = get_mongo_collection(
        collection_name=DB_DEVICE_EXCEPTION_STATUS_INTERVAL_DOCUMENT
    )
    rapid_response_handler = get_mongo_collection(collection_name=DB_RAPID_RESPONSE_DOCUMENT)

    # 标记设备状态时间片库
    updated_record = await device_interval_handler.find_one_and_update(
        {
            "device_code": device_code,
            "start_time": start_time,
            "duration": {"$ne": 0},  # 如果有时长为0的时间片可能会查错记录
        },
        update={"$set": {"reason": update_mark_reason}},
        upsert=False,
        return_document=ReturnDocument.AFTER,
    )
    # 如果是关机(急停，调试)的话，只需要标记时间片的库；如果是中断的话，快反的库也需要标记
    if not updated_record or updated_record["status_code"] in [0, 8, 9]:
        return

    # 标记快反库
    await rapid_response_handler.find_one_and_update(
        filter={
            "device_code": device_code,
            "start_time": start_time,
        },
        update={"$set": {"reason": update_mark_reason}},
        upsert=False,
    )
    # 记录频次数据
    await incr_rapid_response_count(reason_class, reason_detail)


async def incr_rapid_response_count(reason_class: str, reason_detail: str):
    """
    记录快反的频次
    :param reason_class:
    :param reason_detail:
    :return:
    """
    rapid_response_count_handler = get_mongo_collection(
        collection_name=RAPID_RESPONSE_REASON_COUNT_DB
    )
    await rapid_response_count_handler.find_one_and_update(
        filter={
            "reason_class": reason_class,
            "reason_detail": reason_detail,
        },
        update={
            "$inc": {"value": 1},
        },
        upsert=True,
    )
